<?php

declare(strict_types=1);

namespace App\Hoenix\Job;

use App\Hoenix\Model\HoenixIndex;
use App\Hoenix\Model\HoenixIndexText;
use App\Hoenix\Model\HoenixKeyword;
use App\Hoenix\Model\HoenixKeywordIndex;
use Hyperf\AsyncQueue\Job;

class IndexKeywordJob extends Job
{
    public function __construct(public array $data)
    {
    }

    public function handle(): void
    {
        try {
            $keyword = "'" . $this->data['title'] . ';' . ($this->data['desc'] ?? '') . "'";
            $cmd = 'python3 ' . dirname(BASE_PATH) . '/py/cut.py ';
            exec($cmd . $keyword, $output);
            if (empty($output)) return;
            $filtered_words = json_decode($output[0], true);

            preg_match_all('/(https?:\/\/[^\s]+)/', $this->data['title'], $matches);
            $urls = $matches[0];
            $tempText = preg_replace('/(https?:\/\/[^\s]+)/', 'URLTPL', $this->data['title']);
            $txt = preg_replace('/[^\p{L}\p{N}\s]/u', ' ', $tempText);
            $txt = preg_replace('/\s+/', ' ', $txt);
            foreach ($urls as $url) $txt = preg_replace('/URLTPL/', $url, $txt, 1);
            $this->data['title'] = mb_strcut($txt, 0, 64);
            $this->data['c_at'] = date('Y-m-d H:i:s');
            if (isset($this->data['is_chat'])) {
                $md = HoenixIndex::query()->where(['chat_id' => $this->data['chat_id']])->whereIn('type', [1, 2])->first();
                if ($md) $md->fill($this->data)->save(); else HoenixIndex::query()->create($this->data);
            } else {
                if (empty($this->data['chat_id'])) $map = ['url' => $this->data['url'], 'type' => 8];
                else $map = ['chat_id' => $this->data['chat_id'], 'msg_id' => $this->data['msg_id']];
                $md = HoenixIndex::query()->where($map)->first();
                if (!$md) $md = HoenixIndex::query()->create($this->data);
            }
            if (!$md) {
                sys_notify('IndexKeywordJob:' . json_encode($this->data, JSON_UNESCAPED_UNICODE));
                return;
            }
            if ($md->wasRecentlyCreated && !in_array($md->type, [0, 1, 2])) HoenixIndexText::query()->create(['idx' => $md->id, 'text' => ($this->data['desc'] ?? '') ?: $this->data['title']]);
            $in = [];
            $exist = HoenixKeyword::query()->whereIn('kw', $filtered_words)->pluck('kw')->toArray();
            foreach (array_diff($filtered_words, $exist) as $word) if (mb_strlen($word) <= 32) $in[] = ['kw' => $word];
            if ($in) HoenixKeyword::query()->insert($in);
            $this->kidx($filtered_words, $md);
            if (!in_array($md->type, [1, 2])) {
                $chat = HoenixIndex::query()->where(['chat_id' => $md->chat_id])->whereIn('type', [1, 2])->first();
                if ($chat) $this->kidx($filtered_words, $chat);
            }
        } catch (\Throwable $throwable) {
            sys_notify($throwable->getMessage() . $throwable->getTraceAsString());
        }
    }

    public function kidx(array $filtered_words, HoenixIndex $md): void
    {
        $in = [];
        $exist = HoenixKeywordIndex::query()->where(['idx' => $md->id])->pluck('kid')->toArray();
        $kids = HoenixKeyword::query()->whereIn('kw', $filtered_words)->pluck('id')->toArray();
        foreach (array_diff($kids, $exist) as $kid) {
            $in[] = ['idx' => $md->id, 'kid' => $kid];
        }
        if ($in) HoenixKeywordIndex::query()->insert($in);
    }
}